/*******************************************************************************
  * 文件：TKComm.c
  * 作者：djy
  * 版本：v1.0.0
  * 日期：2024-02-22
  * 说明：触摸芯片通讯组件
*******************************************************************************/
/* 头文件 *********************************************************************/
#include "TKComm.h"
#include "Serial.h"
#include "ComFun.h"
#include "DevInfor.h"
#include "CRC.h"

/* 宏定义 *********************************************************************/
/* 类型定义 *******************************************************************/
/* 变量定义 *******************************************************************/
/* 函数声明 *******************************************************************/
/* 函数定义 *******************************************************************/

/*******************************************************************************
  * 函数名: BoardCommFrameCheck
  * 功  能  ：底板通讯接收报文校验
  * 参  数 ：U8 au8Data[]：待校验的数据
  *         U8 u8len：数据长度
  * 返回值：NULL:非法报文
  *         BoardFrame_ts *：合法报文地址
  * 说  明 ：无
*******************************************************************************/
static TKFrame_ts* TKCommFrameCheck(U8 au8Data[],U8 u8len)
{
    U8 u8Index;

    // 遍历所有数据
    for(u8Index = 0;u8Index < u8len;u8Index++)
    {
        // 寻找帧头
        if(au8Data[u8Index] == 0xE2)
        {
            // 指针转换
            TKFrame_ts *psFrame = (TKFrame_ts *)(au8Data+u8Index);

            // 剩余数据量不足以组成最短的报文
            if((u8len - u8Index) < U8_TOUCH_KEY_COMM_FRAMELEN)
            {
                // 返回NULL
                return NULL;
            }
            
            // 目的地址不对
            if(U8_TOUCH_KEY_COMM_DESTADDR != psFrame->au8DestAddr)
            {
                // 继续遍历
                continue;
            }

            // 源地址不对
            if(U8_TOUCH_KEY_COMM_SOURCEADDR != psFrame->au8SourceAddr)
            {
                // 继续遍历
                continue;
            }

            // 命令不对
            if(U8_TOUCH_KEY_COMM_CMD != psFrame->u8Cmd)
            {
                // 继续遍历
                continue;
            }

            // 数据长度不对
            if(U8_TOUCH_KEY_COMM_DATALEN != psFrame->u8DataLen)
            {
                // 继续遍历
                continue;
            }

            // 数据块个数不对
            if(U8_TOUCH_KEY_COMM_DBANUMS != psFrame->u8DBANums)
            {
                // 继续遍历
                continue;
            }

            // 数据块地址不对
            if(U8_TOUCH_KEY_COMM_DBAADDRH != psFrame->u8DBAAddrH || U8_TOUCH_KEY_COMM_DBAADDRL != psFrame->u8DBAAddrL)
            {
                // 继续遍历
                continue;
            }

            // 数据块长度不对
            if(U8_TOUCH_KEY_COMM_DBALEN != psFrame->u8DBALen)
            {
                // 继续遍历
                continue;
            }            
        
            // 帧尾不对
            if(U8_TOUCH_KEY_COMM_ETX != psFrame->u8ETX)
            {
                // 继续遍历
                continue;
            }   
        
            // CRC16校验不通过
            U16 u16CRC = CRC_CalcValue(&(psFrame->u8Seq),
                                       U8_TOUCH_KEY_COMM_FRAMELEN-4,
                                       0x1021);
            
            if(psFrame->u8CRC[0] != (U8)(u16CRC >> 8) || psFrame->u8CRC[1] != (U8)u16CRC)
            {
                // 继续遍历
                continue;
            }

            // 校验通过，返回合法报文指针
            return psFrame;
        }
    }

    // 遍历完所有数据，仍未找到合法报文
    return NULL;
}

/*******************************************************************************
  * 函数名: BoardCommRecvFrameTask
  * 功  能：底板通讯接收报文解析任务
  * 参  数：无
  * 返回值：无
  * 说  明：无
*******************************************************************************/
void TKCommRecvFrameTask(void)
{
    U8 au8RecvData[34];

    // 清空缓冲区
    memset(au8RecvData,0x00,sizeof(au8RecvData));
    
    // 将数据从串口接收缓冲区取出
    U8 u8RecvLen = SerialRxFIFOPeek(SERIAL_TOUCH_KEY_CHN,au8RecvData,sizeof(au8RecvData));

    if(u8RecvLen != 0)
    {
        // 报文合法性校验
        TKFrame_ts* psFrame = TKCommFrameCheck(au8RecvData,u8RecvLen);

        if(psFrame != NULL)
        {
            // 合法报文处理，缓存按键值
            // U8 u8FrameLen = BoardCommFrame_Dispatch(psFrame);
            Dev_SetKeyValue(Get_BigEndian_Value(psFrame->u8KeyValue,4));     // 0207去掉，后期添加对传输数据的处理
              
            // 清空处理过的数据 - 可在此处打断点来确认传输的键值 
            // 键值被存储在 psFrame 的 u8KeyValue 中
            SerialRxFIFOClear(SERIAL_TOUCH_KEY_CHN,17 + ((U32)psFrame - (U32)au8RecvData));
        }
        else
        {
            // 非法报文且缓冲区数据长度超过34个字节
            if(u8RecvLen >= 34)
            {
                // 清空串口接收缓冲区，防止数据堆积 - 几乎没有进到此处的
                SerialRxFIFOClear(SERIAL_TOUCH_KEY_CHN,u8RecvLen);
            }
        }
    }
}

/*******************************************************************************
  * 函数名：TKComm_Init
  * 功  能：初始化
  * 参  数：无
  * 返回值：无
  * 说  明：无
*******************************************************************************/
void TKComm_Init(void)
{
    // 串口初始化
    Serial_Init();
    
    // 创建解析任务
    OS_TaskCreate(TKCommRecvFrameTask);
}


/***************************** 文件结束 ***************************************/
